namespace Yaaf.WP7.NativeAccess.Registry.Internals.AllDevices
{
    using System;
    using System.Collections.Generic;

    using Yaaf.WP7.NativeAccess.ComWrapper.AllDevices.COM_Native;

    public class RegistryBase : IRegistryAccess
    {
        private NativeRegistry native;

        public RegistryBase()
        {
            native = new NativeRegistry();
        }

        public virtual void SetValue(RootKey root, string subKey, string valueName, object value, RegistryValueKind valueKind)
        {
            var rootName = GetRoot(root);
            switch (valueKind)
            {
                case RegistryValueKind.DWord:
                    checked
                    {
                        native.SetDwordValue(rootName, subKey, valueName, (uint)value);
                    }
                    break;
                case RegistryValueKind.String:
                    native.SetStringValue(rootName, subKey, valueName, (string)value);
                    break;
                case RegistryValueKind.Long:
                    checked
                    {
                        native.SetDwordValue(rootName, subKey, valueName, (uint)value);
                    }
                    break;
                default:
                    throw new NotSupportedException("This valuekind is not supported jet!");
            }
        }

        public virtual void DeleteKey(RootKey root, string subKey)
        {
            throw new NotSupportedException("Deleting a key is not supported jet!");
        }

        public virtual void DeleteValue(RootKey root, string subKey, string valueName)
        {
            throw new NotSupportedException("Deleting a value is not supported jet!");
        }

        public virtual RegistryValueKind GetValueType(RootKey root, string subKey, string valueName)
        {
            var rootName = GetRoot(root);
            return native.GetValueType(rootName, subKey, valueName);
        }

        public virtual object GetValue(RootKey root, string subKey, string valueName)
        {
            var rootName = GetRoot(root);
            switch (GetValueType(root, subKey, valueName))
            {
                case RegistryValueKind.DWord:
                    return native.GetIntValue(rootName, subKey, valueName);
                    break;
                case RegistryValueKind.String:
                    return native.GetStringValue(rootName, subKey, valueName);
                    break;
                default:
                    throw new NotSupportedException("Reading other values than DWord or String are not supported!");
            }
        }

        private string GetRoot(RootKey root)
        {
            return Registry.ToShortRepresentation(root);
        }

        public virtual IEnumerable<string> GetSubKeyNames(RootKey root, string subKey)
        {
            if (string.IsNullOrEmpty(subKey))
            {
                switch (root)
                {
                    case RootKey.E_HKEY_LOCAL_MACHINE:
                        return new List<string>() { "Software", "System", "Services", "ControlPanel", "Ident" };
                        break;
                    case RootKey.E_HKEY_CURRENT_USER:
                        return new List<string>() { "System", "ControlPanel", "Software" };
                }
            }

            if (subKey == "System")
            {
                switch (root)
                {
                    case RootKey.E_HKEY_LOCAL_MACHINE:
                        return new List<string>() { "State", "GDI", "GWE", "AutoDataConfig" };
                        break;
                    case RootKey.E_HKEY_CURRENT_USER:
                        return new List<string>() { "State" };
                }
            }

            return native.GetSubKeys(GetRoot(root), subKey);
        }

        public virtual IEnumerable<string> GetValuesNames(RootKey root, string subKey)
        {
            if (string.IsNullOrEmpty(subKey))
            {
                return new string[0];
            }
            return native.GetSubValuesNames(GetRoot(root), subKey);
        }
    }
}